/*
 * TODO language 
 * Copyright (c) 2010 TODO Team
 * 
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */

#include <iostream>
#include <sstream>
#include "API.h"
#include "types.h"
#include "int.h"

namespace todo { namespace type {
	
Int::Int() : Type("int", TypeManager::numerictype)
{
}

void Int::load(void)
{
	// Methods
	register_method(TODO_PUBLIC, "toString", "string", (MethodPtr)&Int::toString);
	register_method(TODO_PUBLIC, "chr"     , "string", (MethodPtr)&Int::chr     );
	register_method(TODO_PUBLIC, "hex"     , "string", (MethodPtr)&Int::hexVoid );
	register_method(TODO_PUBLIC, "hex"     , "string", (MethodPtr)&Int::hex, 1, TypeList(1, "bool"));
	// Static methods
	register_method(todo::MemberFlags(TODO_STATIC|TODO_PUBLIC), "parseInt" , "int"   ,  (MethodPtr)&Int::parseInt,  1, TypeList(1, "object"));
	register_method(todo::MemberFlags(TODO_STATIC|TODO_PUBLIC), "hexString", "string", (MethodPtr)&Int::staticHex, 1, TypeList(1, "int")   );
}

/**
 * string int::chr()
 */
TODO_METHOD(Int, chr)
{
	char i = int(INT_V(value));

	Value* ret = NEW("string");
	STR_V(ret) = i;

	return ret;
}

/**
 * string int::toString( void )
 */
TODO_METHOD(Int, toString)
{
	std::stringstream str;
	Value *val = NEW("string");

	str << INT_V(value);
	STR_P(val)->assign(str.str());

	return val;
}

/**
 * static int int::parseInt( object ) 
 * - where Value must be of the basic type 'int' or 'string' or 'bool' or 'double'
 * - when the argument isn't instances of that classes, this instance is returned.
 */
TODO_STATIC_METHOD(Int, parseInt)
{
	Value* ret = NEW("int");
	Value* val = ARG(0);
	const Type* arg_type = val->type;
	
	if (arg_type == TypeManager::stringtype || val->type->is_child_of(TypeManager::stringtype)) {
		long v;
		std::istringstream oss(STR_V(val));
		oss >> v;
		INT_V(ret) = v;
		return ret;
	}
	
	if (arg_type == TypeManager::inttype || val->type->is_child_of(TypeManager::stringtype)) {
		INT_V(ret) = INT_V(val);
		return ret;
	}
	
	if (arg_type == TypeManager::booltype || val->type->is_child_of(TypeManager::stringtype)) {
		INT_V(ret) = long(BOOL_V(val));
		return ret;
	}
	
	if (arg_type == TypeManager::doubletype || val->type->is_child_of(TypeManager::stringtype)) {
		INT_V(ret) = long(DOUBLE_V(val));
		return ret;
	}
		
	// Returning the argument given
	return ret;
}

/**
 * static string int::hex( int , bool=true )
 * - Returns an string with the hexadecimal representation of the int given,
 *	if the second argument is given and is false, the '0x' is not inserted
 *	in the returned string.
 */
TODO_STATIC_METHOD(Int, staticHex)
{
	Value* ret = NEW("string");
	long val = INT_V(ARG(0));
	bool showbase = true;
	std::stringstream ss;
	
	if (ARGC() == 2) {
		showbase = BOOL_V(ARG(1));
	}
	
	ss << (showbase ? std::showbase : std::noshowbase) << std::hex << val;

	STR_P(ret)->assign(ss.str());
	
	return ret;
}

/**
 * string int::hex( bool showbase )
 * - Returns an string with the hexadecimal representation.
 * - If showbase is false, he '0x' is not inserted in the string.
 */
TODO_METHOD(Int, hex)
{
	ArgValues arg;
	arg.args[0] = value;
	arg.args[1] = ARG(0);
	
	return staticHex(NULL, &arg);
}

/**
 * string int::hex( void )
 * - Returns an string with the hexadecimal representation.
 */
TODO_METHOD(Int, hexVoid)
{
	ArgValues arg;
	arg.args[0] = value;
	
	return staticHex(NULL, &arg);
}

/**
 * Allocs a int value
 */
Value* Int::alloc()
{
	Value *value = new Value(this);
	
	INT_V(value) = 0;
	value->parent = parent->alloc();
	alloc_value_properties(value);

	return value;
}

/**
 * Copies an int value
 */
Value* Int::copy(const Value* value)
{
	Value* new_value = new Value(this);
	
	INT_V(new_value) = INT_V(value);
	new_value->parent = parent->alloc();
	alloc_value_properties(new_value);
	
	return new_value;
}

/**
 * Dealloc a int value
 */
void Int::dealloc(Value* value)
{
	parent->dealloc(value->parent);
	delete value;
}

}} // todo::type
